/*
 * {comment of class}
 *
 * @author (C) <a href="http://www.carfield.com.hk">Carfield Yim </a>, 2004
 */
package hk.com.carfield.core;

import hk.com.carfield.content.Content;
import hk.com.carfield.item.FileItem;
import hk.com.carfield.item.Item;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.whirlycott.cache.Cache;
import com.whirlycott.cache.CacheConfiguration;
import com.whirlycott.cache.CacheException;

/**
 * @author carfield
 */
public final class CacheManager {
	private final Cache<File, FileItem[]> fileItemCache;

	private final Cache<File, Content> contentCache;

	private final Cache<File, Long> timeCache;

	@SuppressWarnings("unchecked")
	public CacheManager() {
		try {
			final CacheConfiguration cc = com.whirlycott.cache.CacheManager.getConfiguration().get("default");
			cc.setMaxSize(750);
			final com.whirlycott.cache.CacheManager cm = com.whirlycott.cache.CacheManager.getInstance();
			cc.setName("fileItemCache");
			fileItemCache = cm.createCache(cc);
			cc.setName("contentCache");
			contentCache = cm.createCache(cc);
			cc.setName("pageCache");
			timeCache = cm.createCache(cc);
		} catch (final CacheException e) {
			throw new RuntimeException(e);
		}
	}

	public void shutdown() {
		try {
			com.whirlycott.cache.CacheManager.getInstance().shutdown();
		} catch (final CacheException e) {
			throw new RuntimeException(e);
		}
	}

	public void remove(final File file) {
		fileItemCache.remove(file);
		contentCache.remove(file);
	}

	public void clear() {
		fileItemCache.clear();
		contentCache.clear();
	}

	public FileItem[] getSortedPeerFileItems(final Context c, final File directory, final Comparator<Item> fc)
			throws IOException {
		final FileItem[] o = fileItemCache.retrieve(directory);
		if (o == null) {
			final File[] peerFiles = directory.listFiles(c.config.displayFilter());
			final List<FileItem> list = new ArrayList<FileItem>();
			if (peerFiles != null) {
				for (int i = 0; i < peerFiles.length; i++) {
					if (peerFiles[i].isFile()) {
						list.add(FileItem.getFileItem(c, peerFiles[i], false));
					}
				}
			}
			Collections.sort(list, fc);
			final FileItem[] sortedPeer = list.toArray(new FileItem[list.size()]);
			fileItemCache.store(directory, sortedPeer);
			return sortedPeer;
		}
		return o;
	}

	public Content getContent(final Config config, final File file) {
		final Content o = contentCache.retrieve(file);
		final Long lastAccess = timeCache.retrieve(file);
		if (o == null || lastAccess == null || lastAccess < file.lastModified()) {
			final Content content = ContentManager.getContent(config, file);
			contentCache.store(file, content);
			timeCache.store(file, file.lastModified());
			return content;
		}
		return o;
	}
}
